﻿
// U盘偷猎者.cpp : 定义应用程序的入口点。
//

#include "pch.h"
#include "framework.h"
#include "U盘偷猎者.h"

#define MAX_LOADSTRING 100


/*

外部设备改变消息:
    WM_DEVICECHANGE —— 设备改变消息

io设备：
    o output 显示设备：
        显示器 LED屏 灯 音响
    i input 输入设备：
        鼠标 键盘 麦克风

存储设备：
    软盘 光盘 u盘 flush

Dbt.h   存储设备相关的库
    DBT_DEVICEARRIVAL
        已然实现对 u盘 插入的检测
    要实现:
    1.u盘盘符获取
    dbcv_unitmask
    2.文件拷贝


dos命令：      大小写不敏感
   windows + R 输入cmd 弹出控制台（cmd）窗口
   切换盘符 c:
   DIR命令          显示当前文件夹下的文件
   cd命令           切换当前活动文件夹
   ..               当前文件夹的父文件夹（上层文件夹）
   .                当前文件夹
   cls              清屏 不是删除掉了 是把消息往上推了
   xcopy            拷贝文件




*/



// 全局变量:
HINSTANCE hInst;                                // 当前实例
WCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名
HANDLE hConsole;    //控制台句柄




// 此代码模块中包含的函数的前向声明:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);


//把盘符模块中包含的函数的前向声明：
char uMask2char(DWORD uMask);



int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: 在此处放置代码。

    // 初始化全局字符串
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_U, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // 执行应用程序初始化:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_U));

    MSG msg;

    // 主消息循环:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  函数: MyRegisterClass()
//
//  目标: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_U));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_U);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

//
//   函数: InitInstance(HINSTANCE, int)
//
//   目标: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中，我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // 将实例句柄存储在全局变量中

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目标: 处理主窗口的消息。
//
//  WM_COMMAND  - 处理应用程序菜单
//  WM_PAINT    - 绘制主窗口
//  WM_DESTROY  - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    char buf[256] = { 0 };
    static int cnt;
    char panfu;
    switch (message)
    {
    case WM_CREATE:
        //申请控制台
        AllocConsole();
        //获取控制台句柄
        hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        break;

    case WM_DEVICECHANGE:       //设备改变消息

        /*
        sprintf_s(buf, "有设备改变%d\n",cnt++);
        WriteConsole(hConsole, buf, strlen(buf), NULL, NULL);     //写控制台
        */
        

        if (DBT_DEVICEARRIVAL == wParam)
        {
            /*
            sprintf_s(buf, "有设备到达\n");
            WriteConsole(hConsole, buf, strlen(buf), NULL, NULL);     //写控制台
            */
            
        
            PDEV_BROADCAST_HDR pDev = (PDEV_BROADCAST_HDR)lParam;   //windows内核自己开内存 然后把地址赋值给lParam,所以lParam本身是地址
            PDEV_BROADCAST_VOLUME pVol = (PDEV_BROADCAST_VOLUME)pDev;
            //pVol->dbcv_unitmask; //描述盘符情况

            panfu = uMask2char(pVol->dbcv_unitmask);
            sprintf_s(buf, "有u盘插入，盘符为%c\n",panfu);
            WriteConsole(hConsole, buf, strlen(buf), NULL, NULL);     //写控制台
        }



        break;


    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 分析菜单选择:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: 在此处添加使用 hdc 的任何绘图代码...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}


//把盘符模块中包含的函数的前向声明：
char uMask2char(DWORD uMask)
{
    int i;
    for (i = 0; i < 26; i++)
    {
        if ((uMask & 1) == 1)     //最低位为1
        {
            break;
        }
        uMask >>= 1;            //右移一位
    }

    return i + 'A';

}